use dioxus_logger::tracing::{error, info};
use reqwest::{Client, Response};
use serde::{Deserialize, Serialize};
use anyhow::Result;

use crate::global;

#[derive(Serialize, Deserialize, Debug)]
struct ResponseData<T> {
    data: T,
    errmsg: String,
    errno: i32,
}

#[derive(Serialize, Deserialize, Debug)]
struct BasicReq {
    r#type: i32,
    path: Option<String>,
}

#[derive(Serialize, Deserialize, Debug)]
struct LoginRes {
    status: i32,
}

#[derive(Serialize, Deserialize, Debug)]
struct GetListReq {
    r#type: i32,
    pull_type: i32,
}

#[derive(Serialize, Deserialize, Debug)]
struct ListDetail {
    avatar_url: String,
    nick_name: String,
    remark: String,
    wx_account: String,
    wx_id: String,
}

#[derive(Serialize, Deserialize, Debug)]
struct GetGroupRes {
    list: Vec<ListDetail>,
}

#[derive(Serialize, Deserialize, Debug)]
struct SendTextReq {
    r#type: i32,
    wx_id: String,
    msg: String,
}

#[derive(Serialize, Deserialize, Debug)]
struct SendTextRes {
    status: i32,
}

async fn post<T: Serialize>(client: &Client, payload: &T) -> Result<Response> {
    let url = format!("http://localhost:{}/api", global::get_port().0);

    let resp = client.post(&url).json(payload).send().await?;

    Ok(resp)
}

// async fn is_login(client: &Client, send_port: u16, ticker: &mut tokio::time::Interval) -> bool {
//     let payload = BasicReq { r#type: 1, path: None };
//
//     match post(client, &payload, send_port).await {
//         Ok(resp) => {
//             if resp.status().is_success() {
//                 let response: ResponseData<LoginRes> = resp.json().await.unwrap();
//                 info!("Response data: {:?}", response.data);
//
//                 if response.data.status == 1 {
//                     info!("Logged in.");
//                     ticker.tick().await;
//                     return true;
//                 }
//             }
//             false
//         }
//         Err(err) => {
//             error!("Error sending request: {}", err);
//             false
//         }
//     }
// }

async fn is_login_once(client: &Client) -> bool {
    let payload = BasicReq {
        r#type: 1,
        path: None,
    };

    match post(client, &payload).await {
        Ok(resp) => {
            if resp.status().is_success() {
                let response: ResponseData<LoginRes> = resp.json().await.unwrap();
                info!("Login response: {:?}", response);

                if response.data.status == 1 {
                    info!("User is logged in.");
                    return true;
                }
            }
            false
        }
        Err(err) => {
            error!("Error sending request: {}", err);
            false
        }
    }
}

pub async fn get_userinfo(client: &Client) -> Option<global::WxUser> {
    let payload = BasicReq {
        r#type: 3,
        path: None,
    };

    match post(client, &payload).await {
        Ok(resp) => {
            if resp.status().is_success() {
                let response: ResponseData<global::WxUser> = resp.json().await.unwrap();
                info!("User info response: {:?}", response);
                return Some(response.data);
            }
            None
        }
        Err(err) => {
            error!("Error sending request: {}", err);
            None
        }
    }
}

async fn get_user_list(client: &Client) -> Vec<ListDetail> {
    let payload = GetListReq {
        r#type: 5,
        pull_type: 1,
    };

    match post(client, &payload).await {
        Ok(resp) => {
            if resp.status().is_success() {
                let response: ResponseData<GetGroupRes> = resp.json().await.unwrap();
                info!("User list response: {:?}", response);
                return response.data.list;
            }
            Vec::new()
        }
        Err(err) => {
            error!("Error sending request: {}", err);
            Vec::new()
        }
    }
}

async fn get_group_list(client: &Client) -> Vec<ListDetail> {
    let payload = GetListReq {
        r#type: 5,
        pull_type: 2,
    };

    match post(client, &payload).await {
        Ok(resp) => {
            if resp.status().is_success() {
                let response: ResponseData<GetGroupRes> = resp.json().await.unwrap();
                info!("Group list response: {:?}", response);
                return response.data.list;
            }
            Vec::new()
        }
        Err(err) => {
            error!("Error sending request: {}", err);
            Vec::new()
        }
    }
}

async fn send_text(client: &Client, wx_id: &str, msg: &str) -> bool {
    let payload = SendTextReq {
        r#type: 7,
        wx_id: wx_id.to_string(),
        msg: msg.to_string(),
    };

    match post(client, &payload).await {
        Ok(resp) => {
            if resp.status().is_success() {
                let response: ResponseData<SendTextRes> = resp.json().await.unwrap();
                info!("Send text response: {:?}", response);

                return response.data.status == 0;
            }
            false
        }
        Err(err) => {
            error!("Error sending request: {}", err);
            false
        }
    }
}

async fn send_text_everyone(client: &Client, list: Vec<ListDetail>) {
    for elem in list {
        if send_text(client, &elem.wx_id, &format!("你好啊，{}", elem.nick_name)).await {
            info!("Successfully sent message to {}", elem.nick_name);
        } else {
            info!("Failed to send message to {}", elem.nick_name);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn get_user() {
        let client = Client::new();

        let info = get_userinfo(&client).await;

        match info {
            Some(user) => {
                println!("user: {user:#?}");
            }
            None => {
                println!("未获取到当前用户")
            }
        }
    }
}

// #[tokio::main]
// async fn main() {
//     // Initialize the client
//     let client = Client::new();
//     let send_port = 8080; // You can replace this with the actual port
//
//     // Example usage of functions
//     if is_login_once(&client, send_port).await {
//         let user_info = get_info(&client, send_port).await;
//         if let Some(user) = user_info {
//             info!("User info: {:?}", user);
//         }
//
//         let user_list = get_user_list(&client, send_port).await;
//         send_text_everyone(&client, send_port, user_list).await;
//     }
// }
